package com.qf.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.mapper.AccountMapper;
import com.qf.pojo.Account;
import com.qf.service.AccountService;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

//@Service
//@Transactional //当前实现类中所有方法都会进行事务控制
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Override
    public List<Account> findAll() {
        return accountMapper.findAll();
    }

    @Override
    public PageInfo<Account> findPage(int pageNum, int size) {
        PageHelper.startPage(pageNum,size);

        List<Account> accounts = accountMapper.findAll();

        return new PageInfo<>(accounts);
    }

    @Override
    public void go(Double money, String inName, String outName) {

    }

    @Override
    public void saveLog() {

    }

    /**
     * mysql事务：
     *  四大特性： 原子性、隔离性、一致性、持久性
     *
     *  隔离级别：读未提交（read uncommitted）、读已提交（read committed -RC）、可重复读(repeatable read -RR)、串行化(serializable)
     *
     *  RC & RR 区别?
     *      RC:A和B事务都在同时执行事务操作，A事务提交后，B事务是可以直接读取到A事务提交后的事务的 -- B事务在前后两次查询过程中数据不一致的
     *      RR:A和B事务都在同时执行事务操作
     *          A事务提交之前，B事务没有进行过查询操作，一旦A事务提交，B事务是可以查询到A事务提交的数据的
     *          A事务提交之前，B事务进行过查询操作，一旦A事务提交，B事务是不可以查询到A事务提交的数据的
     *          --- 保障B事务在前后查询过程中数据的一致性
     *
     *  读问题：
     *      脏读
     *      不可重复度
     *      幻读
     */

    /**
         propagation:
         isolation: 隔离级别.  spring的事务隔离级别和数据库的事务隔离级别是不是一个概念？？？ 是
         timeout: 事务超时时间. -1 永不超时
         readOnly: 是否只读事务.默认false，但是如果在类上加上这个@Transactional注解，需要给查询方法配置为true
         rollbackFor: 指定什么类型的异常发生回滚，一般我们会设置为Exception
         noRollbackFor

         ***默认情况下，spring进行事务控制时，只在发生RuntimeException&Error异常时才会进行事务回滚
     */
    @Transactional(rollbackFor = Exception.class)
    public int transfer(Double money, String inName, String outName) throws InterruptedException, ParseException {
        //转出
        accountMapper.updateMoneyByName(outName,-money);

//        int i = 1/0;
//        Thread.sleep(5000);

        //抛出是的编译期异常
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.parse("2023/08/03");

        //转入
        accountMapper.updateMoneyByName(inName,money);

        return 1;
    }
}
